#pragma once
#include "nnse_support.h"

namespace nnse
{
	template <class T, class U> public ref class layer abstract
	{
		// Constructor and Destructor
			public: layer(MLP<T, U>^ p, unsigned int l_n);
			public: virtual ~layer();
		// Member Variables and their Accessor Functions
			// parent - the MLP to which this layer belongs
				private: MLP<T, U>^ parent;
				public: problem<T, U>^ get_parent_problem();
				public: MLP<T, U>^ get_parent_MLP();
			// number - the layer's number relative to the other layers in the parent MLP
				private: unsigned int number;
				public: unsigned int get_number();
				protected: void put_number(unsigned int n);
			// number_of_neurons - the number of neurons in this layer
				private: unsigned int number_of_neurons;
				public: unsigned int get_number_of_neurons();
				protected: void put_number_of_neurons(unsigned int n_n);
			// neurons - the neurons in this layer
				protected: array<neuron<T, U>^>^ neurons;
				public: neuron<T, U>% get_neuron(unsigned int n_n);
				protected: virtual void put_neurons()=0;
			// layer_form - the layer's user interface
				protected: SimpleGUI::Layer<T, U>^ layer_form;
		// Worker Functions
			public: virtual void forward(layer<T, U>% next_layer, bool update_flag);
			public: virtual U reverse(layer<T, U>% next_layer);
		// GUI Functions
			public: void display_form();
			public: void invalidate_form();
			public: void display_neurons();
		// Serialisation Functions
			public: virtual void read(std::wifstream& in);
			public: virtual void write(std::wofstream& out);
			public: virtual void display(std::wofstream& out);
	};
	template <class T, class U> std::wifstream& operator>>(std::wifstream& in, layer<T, U>% l);
	template <class T, class U> std::wofstream& operator<<(std::wofstream& out, layer<T, U>% l);
}
